package com.nlgc365.designpattern.Chapter04_Pattern.Creation.P01_Singleton.Usage.IDGenerators;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 单例模式-饱汉式
 * 功能: ID自增生成器
 * 通过双重检测, 在保证了线程安全的前提下, 保证了只有在创建对象的时候才加锁, 保证了性能.
 * 存在问题: 多线程创建实例的时候, 可能由于CPU存在指令重排, 导致多线程在创建实例时候可能有的线程获取到实例为null
 */
public class IdGenerator4 {

    private AtomicLong atomicLong = new AtomicLong(0);

    private static IdGenerator4 idGenerator;

    //私有构造函数
    private IdGenerator4() {
    }

    //如果还没有创建实例才创建
    public static IdGenerator4 getInstance() {
        //双重检测, 目的, 仅仅在需要创建实例的时候加锁
        if (idGenerator == null) {
            synchronized (IdGenerator4.class) {//为什么要双层检测: 因为第一次检测的时候, 可能多个线程同时都判断为null, 于是都在等待该处等待锁
                if (idGenerator == null) {
                    idGenerator = new IdGenerator4(); // 存在问题: 这里可能存在CPU重排序
                }
            }
        }
        return idGenerator;
    }

    /**
     * 生成自增ID
     *
     * @return 返回ID
     */
    public long getId() {
        return atomicLong.getAndIncrement();
    }
}
